lib: Add a private copy of checksum-instream
authorColin Walters <walters@verbum.org>
Mon, 13 Mar 2017 19:40:24 +0000 (15:40 -0400)
committerAtomic Bot <atomic-devel@projectatomic.io>
Mon, 20 Mar 2017 18:32:40 +0000 (18:32 +0000)
The current `OstreeChecksumInputStream` is public due to a historical
mistake.  I'd like to add an OpenSSL checksum backend, but that's
harder without breaking this API.

Let's ignore it and create a new private version, so it's easier to do the
GLib/OpenSSL abstraction in one place.

Closes: #738
Approved by: jlebon

Makefile-otutil.am
src/libostree/ostree-repo-commit.c
src/libotutil/ot-checksum-instream.c [new file with mode: 0644]
src/libotutil/ot-checksum-instream.h [new file with mode: 0644]
src/libotutil/otutil.h

index ee892a70aedbe9bffee89ffebd9ef5f3ee22b67d..5b6d4e481f11d2678a908af99b74fc6bb0627060 100644 (file)
@@ -22,6 +22,8 @@ noinst_LTLIBRARIES += libotutil.la
 libotutil_la_SOURCES = \
        src/libotutil/ot-checksum-utils.c \
        src/libotutil/ot-checksum-utils.h \
+       src/libotutil/ot-checksum-instream.c \
+       src/libotutil/ot-checksum-instream.h \
        src/libotutil/ot-fs-utils.c \
        src/libotutil/ot-fs-utils.h \
        src/libotutil/ot-keyfile-utils.c \
index f6129ca6b35340ed2c991915161d5e6a03d49423..d02154f895ad8459d5f9a92b86fda24275d0ffde 100644 (file)
@@ -619,12 +619,11 @@ write_object (OstreeRepo         *self,
   OstreeRepoMode repo_mode;
   g_autofree char *temp_filename = NULL;
   g_autofree guchar *ret_csum = NULL;
-  glnx_unref_object OstreeChecksumInputStream *checksum_input = NULL;
+  glnx_unref_object OtChecksumInstream *checksum_input = NULL;
   g_autoptr(GInputStream) file_input = NULL;
   g_autoptr(GFileInfo) file_info = NULL;
   g_autoptr(GVariant) xattrs = NULL;
   gboolean have_obj;
-  GChecksum *checksum = NULL;
   gboolean temp_file_is_regular;
   gboolean temp_file_is_symlink;
   glnx_fd_close int temp_fd = -1;
@@ -654,11 +653,7 @@ write_object (OstreeRepo         *self,
   repo_mode = ostree_repo_get_mode (self);
 
   if (out_csum)
-    {
-      checksum = g_checksum_new (G_CHECKSUM_SHA256);
-      if (input)
-        checksum_input = ostree_checksum_input_stream_new (input, checksum);
-    }
+    checksum_input = ot_checksum_instream_new (input, G_CHECKSUM_SHA256);
 
   if (objtype == OSTREE_OBJECT_TYPE_FILE)
     {
@@ -778,11 +773,11 @@ write_object (OstreeRepo         *self,
       temp_file_is_regular = TRUE;
     }
 
-  if (!checksum)
+  if (!checksum_input)
     actual_checksum = expected_checksum;
   else
     {
-      actual_checksum = g_checksum_get_string (checksum);
+      actual_checksum = ot_checksum_instream_get_string (checksum_input);
       if (expected_checksum && strcmp (actual_checksum, expected_checksum) != 0)
         {
           g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
@@ -892,16 +887,18 @@ write_object (OstreeRepo         *self,
   else
     self->txn_stats.content_objects_total++;
   g_mutex_unlock (&self->txn_stats_lock);
-      
-  if (checksum)
-    ret_csum = ot_csum_from_gchecksum (checksum);
+
+  if (checksum_input)
+    {
+      g_assert (actual_checksum);
+      ret_csum = ostree_checksum_to_bytes (actual_checksum);
+    }
 
   ret = TRUE;
   ot_transfer_out_value(out_csum, &ret_csum);
  out:
   if (temp_filename)
     (void) unlinkat (self->tmp_dir_fd, temp_filename, 0);
-  g_clear_pointer (&checksum, (GDestroyNotify) g_checksum_free);
   return ret;
 }
 
diff --git a/src/libotutil/ot-checksum-instream.c b/src/libotutil/ot-checksum-instream.c
new file mode 100644 (file)
index 0000000..14d5b5f
--- /dev/null
@@ -0,0 +1,129 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ * 
+ * Copyright (C) 2017 Colin Walters <walters@verbum.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include "ot-checksum-instream.h"
+
+G_DEFINE_TYPE (OtChecksumInstream, ot_checksum_instream, G_TYPE_FILTER_INPUT_STREAM)
+
+struct _OtChecksumInstreamPrivate {
+  GChecksum *checksum;
+};
+
+static gssize   ot_checksum_instream_read         (GInputStream         *stream,
+                                                           void                 *buffer,
+                                                           gsize                 count,
+                                                           GCancellable         *cancellable,
+                                                           GError              **error);
+
+static void
+ot_checksum_instream_finalize (GObject *object)
+{
+  OtChecksumInstream *self = (OtChecksumInstream*)object;
+
+  g_checksum_free (self->priv->checksum);
+
+  G_OBJECT_CLASS (ot_checksum_instream_parent_class)->finalize (object);
+}
+
+static void
+ot_checksum_instream_class_init (OtChecksumInstreamClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  GInputStreamClass *stream_class = G_INPUT_STREAM_CLASS (klass);
+
+  g_type_class_add_private (klass, sizeof (OtChecksumInstreamPrivate));
+
+  object_class->finalize = ot_checksum_instream_finalize;
+  stream_class->read_fn = ot_checksum_instream_read;
+}
+
+static void
+ot_checksum_instream_init (OtChecksumInstream *self)
+{
+  self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, OT_TYPE_CHECKSUM_INSTREAM, OtChecksumInstreamPrivate);
+
+}
+
+OtChecksumInstream *
+ot_checksum_instream_new (GInputStream    *base,
+                          GChecksumType    checksum_type)
+{
+  OtChecksumInstream *stream;
+
+  g_return_val_if_fail (G_IS_INPUT_STREAM (base), NULL);
+
+  stream = g_object_new (OT_TYPE_CHECKSUM_INSTREAM,
+                         "base-stream", base,
+                         NULL);
+  stream->priv->checksum = g_checksum_new (checksum_type);
+
+  return (OtChecksumInstream*) (stream);
+}
+
+static gssize
+ot_checksum_instream_read (GInputStream  *stream,
+                           void          *buffer,
+                           gsize          count,
+                           GCancellable  *cancellable,
+                           GError       **error)
+{
+  OtChecksumInstream *self = (OtChecksumInstream*) stream;
+  GFilterInputStream *fself = (GFilterInputStream*) self;
+  gssize res = -1;
+
+  res = g_input_stream_read (fself->base_stream,
+                             buffer,
+                             count,
+                             cancellable,
+                             error);
+  if (res > 0)
+    g_checksum_update (self->priv->checksum, buffer, res);
+
+  return res;
+}
+
+void
+ot_checksum_instream_get_digest (OtChecksumInstream *stream,
+                                 guint8          *buffer,
+                                 gsize           *digest_len)
+{
+  g_checksum_get_digest (stream->priv->checksum, buffer, digest_len);
+}
+
+guint8*
+ot_checksum_instream_dup_digest (OtChecksumInstream *stream,
+                                 gsize              *ret_len)
+{
+  gsize len = 32;
+  guchar *ret = g_malloc (len);
+  g_checksum_get_digest (stream->priv->checksum, ret, &len);
+  g_assert (len == 32);
+  if (ret_len)
+    *ret_len = len;
+  return ret;
+}
+
+char *
+ot_checksum_instream_get_string (OtChecksumInstream *stream)
+{
+  return g_strdup (g_checksum_get_string (stream->priv->checksum));
+}
diff --git a/src/libotutil/ot-checksum-instream.h b/src/libotutil/ot-checksum-instream.h
new file mode 100644 (file)
index 0000000..78a5d44
--- /dev/null
@@ -0,0 +1,64 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*-
+ *
+ * Copyright (C) 2011 Colin Walters <walters@verbum.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ */
+
+#pragma once
+
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define OT_TYPE_CHECKSUM_INSTREAM         (ot_checksum_instream_get_type ())
+#define OT_CHECKSUM_INSTREAM(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), OT_TYPE_CHECKSUM_INPUT_STREAM, OtChecksumInstream))
+#define OT_CHECKSUM_INSTREAM_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), OT_TYPE_CHECKSUM_INPUT_STREAM, OtChecksumInstreamClass))
+#define OT_IS_CHECKSUM_INSTREAM(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), OT_TYPE_CHECKSUM_INPUT_STREAM))
+#define OT_IS_CHECKSUM_INSTREAM_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), OT_TYPE_CHECKSUM_INPUT_STREAM))
+#define OT_CHECKSUM_INSTREAM_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), OT_TYPE_CHECKSUM_INPUT_STREAM, OtChecksumInstreamClass))
+
+typedef struct _OtChecksumInstream         OtChecksumInstream;
+typedef struct _OtChecksumInstreamClass    OtChecksumInstreamClass;
+typedef struct _OtChecksumInstreamPrivate  OtChecksumInstreamPrivate;
+
+struct _OtChecksumInstream
+{
+  GFilterInputStream parent_instance;
+
+  /*< private >*/
+  OtChecksumInstreamPrivate *priv;
+};
+
+struct _OtChecksumInstreamClass
+{
+  GFilterInputStreamClass parent_class;
+};
+
+GType          ot_checksum_instream_get_type     (void) G_GNUC_CONST;
+
+OtChecksumInstream * ot_checksum_instream_new          (GInputStream   *stream, GChecksumType   checksum);
+
+void   ot_checksum_instream_get_digest (OtChecksumInstream *stream,
+                                        guint8          *buffer,
+                                        gsize           *digest_len);
+
+guint8* ot_checksum_instream_dup_digest (OtChecksumInstream *stream,
+                                         gsize              *ret_len);
+char * ot_checksum_instream_get_string (OtChecksumInstream *stream);
+
+G_END_DECLS
index c66d563413bf04719ec9c2cfc509ccd8815cbd01..f6158de86948466adbc4050612d88175a5df2a4c 100644 (file)
@@ -53,5 +53,6 @@
 #include <ot-checksum-utils.h>
 #include <ot-gpg-utils.h>
 #include <ot-log-utils.h>
+#include <ot-checksum-instream.h>
 
 void ot_ptrarray_add_many (GPtrArray  *a, ...) G_GNUC_NULL_TERMINATED;